const fs = require("fs");
const path = require("path");
const os = require("os");
const ExifTool = require("exiftool-vendored").ExifTool;
const ExifImage = require("exif").ExifImage;
/**
 * 获取文件的详细信息。
 * @param {string} filePath - 文件路径。
 * @returns {Promise<object>} 返回一个对象，该对象包含以下属性：
 *  - fsize: 文件大小。
 *  - ftype: 文件类型（如"PIC", "AUDIO", "VIDEO", "DOC", "OTHER"）。
 *  - ctime: 文件的创建时间。
 *  - mtime: 文件的最后修改时间。
 *  - shootTime: 文件的拍摄时间（如果可用）或创建时间。
 */
async function getFileDetails(filePath) {
  const stats = await fs.promises.stat(filePath);
  const fsize = stats.size;
  const ctime = stats.ctime.getTime();
  const mtime = stats.mtime.getTime();

  let ftype;

  const ext = path.extname(filePath).toLowerCase();
  const cleanedExt = ext.startsWith(".") ? ext.slice(1) : ext;

  switch (cleanedExt) {
    // 图片
    case "jpg":
    case "jpeg":
    case "png":
    case "gif":
    case "bmp":
    case "tif":
    case "tiff":
    case "webp":
    case "ico":
    case "heic":
    case "raw":
    case "svg":
    case "psd":
      ftype = "PIC";
      break;

    // 音频
    case "mp3":
    case "wav":
    case "flac":
    case "m4a":
    case "aac":
    case "ac3":
    case "ogg":
    case "wma":
    case "alac":
    case "amr":
    case "ape":
    case "mka":
    case "opus":
    case "ra":
    case "dts":
      ftype = "AUDIO";
      break;

    // 视频
    case "mp4":
    case "avi":
    case "mkv":
    case "mov":
    case "wmv":
    case "flv":
    case "webm":
    case "m4v":
    case "3gp":
    case "3g2":
    case "f4v":
    case "vob":
    case "ogv":
    case "asf":
    case "rm":
    case "rmvb":
    case "ts":
    case "mpg":
    case "mpeg":
    case "m2ts":
    case "divx":
      ftype = "VIDEO";
      break;

    // 文档
    case "doc":
    case "docx":
    case "pdf":
    case "txt":
    case "xlsx":
    case "xls":
    case "ppt":
    case "pptx":
    case "odt":
    case "ods":
    case "odp":
    case "rtf":
    case "csv":
    case "md":
    case "tex":
    case "epub":
      ftype = "DOC";
      break;

    // 其他类型
    default:
      ftype = "OTHER";
  }

  let shootTime;
  if (["PIC", "VIDEO", "AUDIO"].includes(ftype)) {
    if (ftype === "PIC") {
      shootTime = await getImageShootTime(filePath);
      if (!shootTime) {
        // shootTime = ctime;
        shootTime = await getShootTime(filePath, ftype, ctime);
      }
    } else {
      shootTime = await getShootTime(filePath, ftype, ctime);
    }
  }

  return {
    fsize,
    ftype,
    ctime,
    mtime,
    shootTime: shootTime ? new Date(shootTime).getTime() : ctime,
  };
}
/**
 * 使用ExifImage库获取图片的拍摄时间。
 * @param {string} filePath - 图片文件路径。
 * @returns {Promise<number|null>} 返回图片的拍摄时间，如果没有找到则返回null。
 */
async function getImageShootTime(filePath) {
  return new Promise((resolve) => {
    try {
      new ExifImage({ image: filePath }, (error, exifData) => {
        if (
          error ||
          !(exifData && exifData.exif && exifData.exif.DateTimeOriginal)
        ) {
          resolve(null);
        } else {
          const arr = exifData.exif.DateTimeOriginal.split(" ");
          arr[0] = arr[0].replace(/:/gi, "/");

          const shootTime = new Date(arr.join(" ")).getTime();
          resolve(shootTime);
        }
      });
    } catch (error) {
      resolve(null);
    }
  });
}

/**
 * 获取文件（图片、音频或视频）的拍摄或创建时间。
 * @param {string} filePath - 文件路径。
 * @param {string} ftype - 文件类型，如"PIC", "AUDIO", "VIDEO"。
 * @param {number} ctime - 文件的创建时间。
 * @returns {Promise<number>} 返回文件的拍摄或创建时间。
 */
async function getShootTime(filePath, ftype, ctime) {
  try {
    // 创建一个 ExifTool 实例，用于读取文件的元数据
    const exiftool = new ExifTool({
      taskTimeoutMillis: 5000,  // 任务超时时间为 5 秒
      minDelayBetweenSpawnMillis: 0,  // 两个任务之间的最小延迟时间
      maxProcs: Math.max(os.cpus().length - 2, 1), // 设置最大进程数，优化性能
    });

    // 读取文件路径指定的文件的元数据
    const metadata = await exiftool.read(filePath);

    // 结束 exiftool，避免进程驻留
    // 更多信息可以参考：https://github.com/photostructure/exiftool-vendored.js#usage
    exiftool.end();

    // 如果文件类型为图片，并且存在 DateTimeOriginal 元数据
    if (ftype === "PIC" && metadata.DateTimeOriginal) {
      return new Date(metadata.DateTimeOriginal).getTime();
    } 
    // 如果文件类型为音频或视频，并且存在 CreateDate 元数据
    else if (
      (ftype === "AUDIO" || ftype === "VIDEO") &&
      metadata.CreateDate
    ) {
      return new Date(metadata.CreateDate).getTime();
    }
  } catch (e) {
    // 如果读取元数据出错，输出错误信息
    console.error("Error reading metadata:", e);
  }
  // 如果没有获取到拍摄或创建时间，返回文件的创建时间
  return ctime;
}


module.exports = { getImageShootTime, getShootTime, getFileDetails };
